#include <brpc/server.h>
#include <butil/logging.h>
#include <thread>

#include "asr.hpp"      // 语音识别模块封装
#include "etcd.hpp"     // 服务注册模块封装
#include "logger.hpp"   // 日志模块封装
#include "speech.pb.h"  // protobuf框架代码

namespace im{
class SpeechServiceImpl :public SpeechService{

public:
    SpeechServiceImpl(const ASRClient::ptr& client):_asr_client(client){}
    ~SpeechServiceImpl(){}
    // 必须重写这个虚函数
    // 定义一个虚函数Echo，用于处理RPC请求  
    virtual void SpeechRecognition(google::protobuf::RpcController* controller, 
                                    const SpeechRecognitionReq* req, 
                                    SpeechRecognitionRsp* resp, 
                                    google::protobuf::Closure* done){
        brpc::ClosureGuard rpc_guard(done);

        resp->set_request_id(req->request_id());
        LOG_INFO("rpc调用语音转文字服务");
        std::string res;
        bool ret = _asr_client->recogize(req->speech_content(), res);
        LOG_DEBUG("语音文件转换内容：{}", res);
        if(ret == false){
            LOG_CRITICAL("{} 语音识别失败！", req->request_id());
            resp->set_success(false);
            resp->set_errmsg(res);
        }else{
            resp->set_success(true);
            resp->set_recognition_result(res);
        }
    }
private:
    ASRClient::ptr _asr_client;
};

class SpeechServer{

public:
    using ptr = std::shared_ptr<SpeechServer>;
    SpeechServer(const ASRClient::ptr asr_client,
                const Registry::ptr &reg_client, 
                const std::shared_ptr<brpc::Server> &server)
                :_asr_client(asr_client),
                _register_client(reg_client),
                _rpc_server(server){}
    ~SpeechServer(){}

    void start(){
        _rpc_server->RunUntilAskedToQuit();
    }

private:
    ASRClient::ptr _asr_client;                 // 百度语音翻译client
    Registry::ptr _register_client;             // 服务注册
    std::shared_ptr<brpc::Server> _rpc_server;  // rpc服务端
};

class SpeechServerBuild{

public:
    void init_asr_client(const std::string& id, const std::string& key, const std::string& secret){
        _asr_client = std::make_shared<ASRClient>(id, key, secret);
    }
    void init_register_client(const std::string& reg_host, const std::string &service_name, const std::string &access_host){
        _register_client = std::make_shared<Registry>(reg_host);
        _register_client->register_server(service_name, access_host);
    }

    void init_rpc_server(uint16_t port, int32_t timeout, uint8_t num_threads){
        if (!_asr_client) {
            LOG_CRITICAL("还未初始化语音识别模块！");
            abort();
        }
        _rpc_server = std::make_shared<brpc::Server>();
        // auto speechImpl = std::make_shared<SpeechServiceImpl>(_asr_client);  // 不能用智能指针，会导致重复释放
        SpeechServiceImpl *speech_service = new SpeechServiceImpl(_asr_client);
        int ret = _rpc_server->AddService(speech_service, brpc::ServiceOwnership::SERVER_OWNS_SERVICE);
        if (ret == -1) {
            LOG_CRITICAL("添加Rpc服务失败！");
            abort();
        }

        brpc::ServerOptions opt;
        opt.num_threads = num_threads;
        opt.idle_timeout_sec = timeout;
        ret = _rpc_server->Start(port, &opt);
        if(ret != 0){
            LOG_CRITICAL("启动服务器失败！");
            abort();
        }
    }

    SpeechServer::ptr build(){
        if (!_asr_client) {
            LOG_CRITICAL("还未初始化语音识别模块！");
            abort();
        }
        if (!_register_client) {
            LOG_CRITICAL("还未初始化服务注册模块！");
            abort();
        }
        if (!_rpc_server) {
            LOG_CRITICAL("还未初始化RPC服务器模块! ");
            abort();
        }
        SpeechServer::ptr server = std::make_shared<SpeechServer>(_asr_client, _register_client, _rpc_server);
        return server;
    }

private:
    ASRClient::ptr _asr_client;                 // 百度语音翻译client
    Registry::ptr _register_client;             // 服务注册
    std::shared_ptr<brpc::Server> _rpc_server;  // rpc服务端
};
}